<template>
  <el-dialog v-model="dialogVisible" title="网红打卡地" width="85%" :before-close="handleClose" center destroy-on-close
    class="hotspot-dialog" top="4vh">
    <div class="hotspot-container">
      <!-- 顶部控制区 -->
      <div class="control-panel">
        <div class="city-selector">
          <el-select v-model="selectedCity" placeholder="选择目的地" size="large" class="city-select"
            @change="handleCityChange">
            <el-option v-for="city in cities" :key="city.code" :label="city.name" :value="city.code">
              <div class="city-option">
                <span class="city-name">{{ city.name }}</span>
                <span class="city-count">{{ getSpotCount(city.code) }}个打卡地</span>
              </div>
            </el-option>
          </el-select>
        </div>

        <div class="filter-tools" v-if="selectedCity">
          <div class="sort-buttons">
            <span class="sort-label">排序:</span>
            <el-radio-group v-model="sortMethod" size="small" @change="sortSpots">
              <el-radio-button label="hot">热度优先</el-radio-button>
              <el-radio-button label="trending">最近上升</el-radio-button>
            </el-radio-group>
          </div>
          <div class="view-switcher">
            <el-tooltip content="网格视图">
              <el-button :type="viewMode === 'grid' ? 'primary' : 'default'" circle size="small"
                @click="viewMode = 'grid'">
                <el-icon>
                  <Grid />
                </el-icon>
              </el-button>
            </el-tooltip>
            <el-tooltip content="列表视图">
              <el-button :type="viewMode === 'list' ? 'primary' : 'default'" circle size="small"
                @click="viewMode = 'list'">
                <el-icon>
                  <Menu />
                </el-icon>
              </el-button>
            </el-tooltip>
          </div>
        </div>
      </div>

      <!-- 城市标语和简介 -->
      <div v-if="selectedCity" class="city-banner" :style="getCityBannerStyle()" :class="{ 'is-loading': loading }">
        <div class="city-info">
          <h2 class="city-title">{{ loading ? '' : getCityName() }}</h2>
          <p class="city-description">{{ loading ? '' : getCityDescription() }}</p>

          <!-- 横幅加载状态 -->
          <template v-if="loading">
            <div class="banner-skeleton">
              <el-skeleton-item variant="h3" style="width: 200px; height: 32px; margin-bottom: 8px;" />
              <el-skeleton-item variant="p" style="width: 80%; height: 16px;" />
            </div>
          </template>
        </div>
      </div>

      <!-- 景点展示区 -->
      <div class="content-area" :class="{ 'no-city': !selectedCity || loading }">
        <!-- 加载状态 -->
        <!-- filepath: d:\D_App5\Journeo\src\components\hotspot\HotspotModal.vue -->
        <!-- 改进加载状态显示 -->
        <div v-if="loading" class="loading-container" :class="viewMode">
          <el-skeleton style="width: 100%" animated :count="viewMode === 'grid' ? 9 : 6" :throttle="500">
            <template #template>
              <!-- 网格视图的精确骨架屏 -->
              <div v-if="viewMode === 'grid'" class="spots-grid-container skeleton-grid">
                <div v-for="i in 9" :key="i" class="spot-card skeleton-card">
                  <div class="spot-image skeleton-image">
                    <el-skeleton-item variant="image" style="width: 100%; height: 180px;" />
                    <div class="spot-overlay"></div>
                    <div class="skeleton-badge"
                      style="position: absolute; top: 12px; right: 12px; width: 50px; height: 24px; border-radius: 20px;">
                      <el-skeleton-item variant="text" style="width: 100%; height: 100%;" />
                    </div>
                    <div class="skeleton-category"
                      style="position: absolute; top: 12px; left: 12px; width: 80px; height: 24px;">
                      <el-skeleton-item variant="text" style="width: 100%; height: 100%;" />
                    </div>
                  </div>
                  <div class="spot-info" style="padding: 16px;">
                    <el-skeleton-item variant="h3" style="width: 70%; height: 24px;" />
                    <div class="skeleton-tags" style="display: flex; margin: 12px 0;">
                      <el-skeleton-item variant="text" style="width: 60px; height: 20px; margin-right: 8px;" />
                      <el-skeleton-item variant="text" style="width: 70px; height: 20px;" />
                    </div>
                    <div class="skeleton-features" style="margin-top: 12px; display: flex;">
                      <el-skeleton-item variant="text" style="width: 80px; height: 16px; margin-right: 12px;" />
                      <el-skeleton-item variant="text" style="width: 70px; height: 16px;" />
                    </div>
                  </div>
                </div>
              </div>

              <!-- 列表视图的精确骨架屏 -->
              <div v-else class="spots-list-container skeleton-list">
                <div v-for="i in 6" :key="i" class="spot-list-item skeleton-list-item">
                  <div class="spot-list-image skeleton-image">
                    <el-skeleton-item variant="image" style="width: 100%; height: 100%;" />
                    <div class="skeleton-badge"
                      style="position: absolute; top: 12px; right: 12px; width: 40px; height: 24px;">
                      <el-skeleton-item variant="text" style="width: 100%; height: 100%;" />
                    </div>
                  </div>
                  <div class="spot-list-info">
                    <div class="spot-list-header">
                      <el-skeleton-item variant="h3" style="width: 50%; height: 24px;" />
                      <div class="skeleton-category-badge">
                        <el-skeleton-item variant="text" style="width: 70px; height: 20px;" />
                      </div>
                    </div>
                    <div class="skeleton-tags" style="display: flex; margin: 12px 0;">
                      <el-skeleton-item variant="text" style="width: 60px; height: 20px; margin-right: 8px;" />
                      <el-skeleton-item variant="text" style="width: 70px; height: 20px; margin-right: 8px;" />
                      <el-skeleton-item variant="text" style="width: 50px; height: 20px;" />
                    </div>
                    <el-skeleton-item variant="p" style="width: 100%; height: 16px; margin: 16px 0;" />
                    <div class="spot-list-footer">
                      <div class="skeleton-metrics">
                        <el-skeleton-item variant="text" style="width: 100px; height: 16px; margin-right: 20px;" />
                        <el-skeleton-item variant="text" style="width: 100px; height: 16px;" />
                      </div>
                      <div class="skeleton-button">
                        <el-skeleton-item variant="button" style="width: 80px; height: 32px;" />
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </template>
          </el-skeleton>
        </div>

        <!-- 未选择城市 -->
        <div v-else-if="!selectedCity" class="empty-state">
          <img src="/images/select-city.svg" alt="选择城市" class="empty-icon" />
          <h3 class="empty-title">选择一个城市开始探索</h3>
          <p class="empty-description">发现当地最受欢迎的网红打卡地</p>

          <div class="popular-cities">
            <div v-for="city in featuredCities" :key="city.code" class="popular-city-card"
              @click="selectedCity = city.code; handleCityChange(city.code)">
              <div class="popular-city-image" :style="`background-image: url(${city.image})`">
                <div class="popular-city-overlay"></div>
                <span class="popular-city-name">{{ city.name }}</span>
                <span class="popular-city-count">{{ getSpotCount(city.code) }}个打卡地</span>
              </div>
            </div>
          </div>
        </div>

        <!-- 网格视图 -->
        <div v-else-if="viewMode === 'grid'" class="spots-grid">
          <transition-group name="spots-fade" tag="div" class="spots-grid-container">
            <div v-for="spot in hotspots" :key="spot.id" class="spot-card" :class="{ 'spotlight': isSpotlight(spot) }"
              @click="viewSpotDetail(spot)">
              <div class="spot-image" :style="{ backgroundImage: `url(${getSpotImage(spot)})` }">
                <div class="spot-overlay"></div>
                <div class="hotness-badge" :class="getHotnessBadgeClass(spot.hotnessScore)">
                  <span class="hotness-icon">
                    <el-icon>
                      <Star />
                    </el-icon>
                  </span>
                  <span class="hotness-value">{{ spot.hotnessScore }}</span>
                </div>
                <div class="spot-category" v-if="getSpotCategory(spot)">
                  {{ getSpotCategory(spot) }}
                </div>
                <div class="spot-quick-info">
                  <div class="like-count">
                    <el-icon>
                      <UserFilled />
                    </el-icon> {{ generateRandomVisitorCount(spot) }}
                  </div>
                  <div class="comment-count">
                    <el-icon>
                      <ChatDotSquare />
                    </el-icon> {{ generateRandomCommentCount(spot) }} 
                  </div>
                </div>
              </div>
              <div class="spot-info">
                <h3 class="spot-name">{{ spot.name }}</h3>
                <div class="spot-tags">
                  <el-tag v-for="(tag, index) in getSpotTags(spot)" :key="index" size="small" effect="plain"
                    :type="getTagType(index)">
                    {{ tag }}
                  </el-tag>
                </div>
                <div class="spot-features">
                  <div class="feature-item" v-if="hasFeature(spot, 'trending')">
                    <el-icon color="#ff6b6b">
                      <TrendCharts />
                    </el-icon> 近期热门
                  </div>
                  <div class="feature-item" v-if="hasFeature(spot, 'photoSpot')">
                    <el-icon color="#4facfe">
                      <Camera />
                    </el-icon> 摄影胜地
                  </div>
                  <div class="feature-item" v-if="hasFeature(spot, 'loved')">
                    <el-icon color="#f5576c">
                      <StarFilled />
                    </el-icon> 深受喜爱
                  </div>
                </div>
              </div>
            </div>
          </transition-group>
        </div>

        <!-- 列表视图 -->
        <div v-else class="spots-list">
          <transition-group name="spots-fade" tag="div" class="spots-list-container">
            <div v-for="spot in hotspots" :key="spot.id" class="spot-list-item"
              :class="{ 'spotlight': isSpotlight(spot) }" @click="viewSpotDetail(spot)">
              <div class="spot-list-image" :style="{ backgroundImage: `url(${getSpotImage(spot)})` }">
                <div class="hotness-badge" :class="getHotnessBadgeClass(spot.hotnessScore)">
                  <span class="hotness-value">{{ spot.hotnessScore }}</span>
                </div>
              </div>
              <div class="spot-list-info">
                <div class="spot-list-header">
                  <h3 class="spot-name">{{ spot.name }}</h3>
                  <div class="spot-category-badge" v-if="getSpotCategory(spot)">
                    {{ getSpotCategory(spot) }}
                  </div>
                </div>
                <div class="spot-tags">
                  <el-tag v-for="(tag, index) in getSpotTags(spot).slice(0, 3)" :key="index" size="small" effect="plain"
                    :type="getTagType(index)">
                    {{ tag }}
                  </el-tag>
                </div>
                <p class="spot-description">{{ getSpotDescription(spot) }}</p>
                <div class="spot-list-footer">
                  <div class="spot-metrics">
                    <span class="metric-item">
                      <el-icon>
                        <UserFilled />
                      </el-icon> {{ generateRandomVisitorCount(spot) }}游客
                    </span>
                    <span class="metric-item">
                      <el-icon>
                        <Picture />
                      </el-icon> {{ generateRandomPhotoCount(spot) }}照片
                    </span>
                  </div>
                  <el-button size="small" type="primary" plain>查看详情</el-button>
                </div>
              </div>
            </div>
          </transition-group>
        </div>
      </div>
    </div>

    <!-- 景点详情弹窗 -->
    <HotspotDetail v-if="selectedSpot" v-model:visible="detailVisible" :spot="selectedSpot" />
  </el-dialog>
</template>

<script setup>
import { ref, computed, watch, onMounted, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import {
  Loading, Star, StarFilled, UserFilled, TrendCharts, Grid,
  Menu, Camera, Picture, ChatDotSquare
} from '@element-plus/icons-vue'
import HotspotDetail from './HotspotDetail.vue'
import HuBeiShengBoWuGuanData from '@/assets/mock/HuBeiShengBoWuGuan.json'
import JiangHanLuData from '@/assets/mock/JiangHanLu.json'
import WuHanDaXueData from '@/assets/mock/WuHanDaXue.json'

// 数据处理与属性
const props = defineProps({
  visible: {
    type: Boolean,
    default: false
  }
})

const emit = defineEmits(['update:visible'])

const dialogVisible = computed({
  get: () => props.visible,
  set: (val) => emit('update:visible', val)
})

// 界面控制
const viewMode = ref('grid') // grid or list
const sortMethod = ref('hot') // hot or trending
const selectedCity = ref('')
const loading = ref(false)
const hotspots = ref([])
const detailVisible = ref(false)
const selectedSpot = ref(null)

// 精选城市
const featuredCities = [
  { name: '武汉', code: 'wuhan', image: '/images/wuhan-banner.jpg' },
  { name: '北京', code: 'beijing', image: '/images/beijing-banner.jpg' },
  { name: '上海', code: 'shanghai', image: '/images/shanghai-banner.jpg' },
  { name: '杭州', code: 'hangzhou', image: '/images/hangzhou-banner.jpg' },
]

// 城市数据
const cities = [
  { name: '北京', code: 'beijing' },
  { name: '上海', code: 'shanghai' },
  { name: '广州', code: 'guangzhou' },
  { name: '深圳', code: 'shenzhen' },
  { name: '杭州', code: 'hangzhou' },
  { name: '成都', code: 'chengdu' },
  { name: '武汉', code: 'wuhan' },
  { name: '西安', code: 'xian' },
  { name: '南京', code: 'nanjing' },
  { name: '重庆', code: 'chongqing' }
]

// 城市描述
const cityDescriptions = {
  'beijing': '探索北京最受欢迎的打卡地，感受古都与现代交融的独特魅力。',
  'shanghai': '魔都上海，中西合璧的建筑风格与潮流时尚的完美融合。',
  'hangzhou': '上有天堂，下有苏杭。诗情画意的美景令人流连忘返。',
  'wuhan': '活力四射的九省通衢，热干面与樱花的城市，充满了烟火气息。',
  'guangzhou': '美食与文化的天堂，体验岭南风情的独特魅力。',
  'shenzhen': '创新与科技的前沿，年轻活力的现代都市风情。',
  'chengdu': '悠闲慢生活的典范，美食与大熊猫的双重享受。',
  'xian': '十三朝古都，感受中国深厚的历史文化底蕴。',
  'nanjing': '六朝古都，山水城林融为一体的人文景观。',
  'chongqing': '雾都山城，独特的地理环境塑造的网红景点。'
}

// 城市背景图
const cityBanners = {
  'beijing': '/images/beijing-banner.jpg',
  'shanghai': '/images/shanghai-banner.jpg',
  'hangzhou': '/images/hangzhou-banner.jpg',
  'wuhan': '/images/wuhan-banner.jpg',
  'default': '/images/travel-banner.jpg'
}

// 模拟数据 - 各城市热门景点
const mockHotspots = {
  beijing: [
    {
      id: 1,
      name: '故宫博物院',
      hotnessScore: 95,
      image: '/images/forbidden-city.jpg',
      category: '历史古迹',
      tags: ['世界文化遗产', '古代建筑', '历史博物馆'],
      features: ['loved', 'photoSpot'],
      isTrending: false
    },
    {
      id: 2,
      name: '颐和园',
      hotnessScore: 88,
      image: '/images/summer-palace.jpg',
      category: '园林景区',
      tags: ['皇家园林', '湖泊', '文化景观'],
      features: ['photoSpot'],
      isTrending: true
    },
    {
      id: 3,
      name: '天安门广场',
      hotnessScore: 86,
      image: '/images/tiananmen.jpg',
      category: '城市地标',
      tags: ['爱国教育', '观景', '城市中心'],
      features: ['loved'],
      isTrending: false
    },
    {
      id: 4,
      name: '北京环球度假区',
      hotnessScore: 82,
      image: '/images/universal-beijing.jpg',
      category: '主题乐园',
      tags: ['刺激项目', '亲子游玩', '娱乐设施'],
      features: ['trending'],
      isTrending: true
    },
    {
      id: 5,
      name: '八达岭长城',
      hotnessScore: 79,
      image: '/images/great-wall.jpg',
      category: '历史古迹',
      tags: ['世界奇迹', '历史遗迹', '登高望远'],
      features: ['photoSpot', 'loved'],
      isTrending: false
    },
    {
      id: 6,
      name: '三里屯',
      hotnessScore: 76,
      image: '/images/sanlitun.jpg',
      category: '商业街区',
      tags: ['时尚', '购物', '酒吧街'],
      features: ['trending'],
      isTrending: true
    },
    {
      id: 7,
      name: '798艺术区',
      hotnessScore: 72,
      image: '/images/798-art-zone.jpg',
      category: '文化艺术',
      tags: ['艺术展览', '文艺', '创意空间'],
      features: ['photoSpot'],
      isTrending: false
    },
    {
      id: 8,
      name: '北京欢乐谷',
      hotnessScore: 70,
      image: '/images/happy-valley.jpg',
      category: '主题乐园',
      tags: ['游乐设施', '表演', '亲子'],
      features: [],
      isTrending: false
    },
    {
      id: 9,
      name: '南锣鼓巷',
      hotnessScore: 67,
      image: '/images/nanluoguxiang.jpg',
      category: '历史街区',
      tags: ['胡同文化', '小吃', '传统建筑'],
      features: [],
      isTrending: false
    },
    {
      id: 10,
      name: '鸟巢',
      hotnessScore: 65,
      image: '/images/birds-nest.jpg',
      category: '城市地标',
      tags: ['奥运建筑', '现代建筑', '体育场馆'],
      features: ['photoSpot'],
      isTrending: false
    }
  ],
  shanghai: [
    {
      id: 11,
      name: '外滩',
      hotnessScore: 92,
      image: '/images/the-bund.jpg',
      category: '城市地标',
      tags: ['夜景', '历史建筑', '江景'],
      features: ['loved', 'photoSpot'],
      isTrending: false
    },
    {
      id: 12,
      name: '迪士尼乐园',
      hotnessScore: 90,
      image: '/images/disney-shanghai.jpg',
      category: '主题乐园',
      tags: ['动漫', '游乐设施', '演出'],
      features: ['trending'],
      isTrending: true
    }
    // 更多上海景点...
  ],
  hangzhou: [
    {
      id: 21,
      name: '西湖',
      hotnessScore: 94,
      image: '/images/west-lake.jpg',
      category: '自然风光',
      tags: ['湖泊', '园林', '世界遗产'],
      features: ['loved', 'photoSpot'],
      isTrending: false
    },
    {
      id: 22,
      name: '灵隐寺',
      hotnessScore: 86,
      image: '/images/lingyin-temple.jpg',
      category: '宗教场所',
      tags: ['佛教', '古建筑', '文化遗产'],
      features: ['photoSpot'],
      isTrending: false
    }
    // 更多杭州景点...
  ],
  wuhan: [
    {
      id: 31,
      name: '湖北省博物馆',
      hotnessScore: 92,
      image: '/images/hubei-museum.jpg',
      category: '文化场所',
      tags: ['博物馆', '历史文物', '编钟'],
      features: ['photoSpot', 'loved'],
      isTrending: false,
      jsonData: HuBeiShengBoWuGuanData
    },
    {
      id: 32,
      name: '江汉路步行街',
      hotnessScore: 88,
      image: '/images/jianghan-road.jpeg',
      category: '商业街区',
      tags: ['购物', '美食', '历史建筑'],
      features: ['trending'],
      isTrending: true,
      jsonData: JiangHanLuData
    },
    {
      id: 33,
      name: '武汉大学',
      hotnessScore: 90,
      image: '/images/wuhan-university.jpg',
      category: '校园风光',
      tags: ['樱花', '建筑', '文艺'],
      features: ['photoSpot', 'loved'],
      isTrending: false,
      jsonData: WuHanDaXueData
    }
    // 更多武汉景点...
  ]
}

// 为其他城市填充模拟数据
for (const city of cities) {
  if (!mockHotspots[city.code]) {
    mockHotspots[city.code] = Array.from({ length: 10 }, (_, i) => {
      const baseScore = Math.floor(Math.random() * 30) + 65; // 65-95之间的随机值
      const categories = ['自然风光', '历史古迹', '城市地标', '文化场所', '商业街区', '主题乐园', '乡村民宿'];
      const categoryIndex = Math.floor(Math.random() * categories.length);

      // 根据类别生成对应的标签
      const tagsByCategory = {
        '自然风光': ['山水', '湖泊', '森林', '风景区', '观景台', '自然保护区'],
        '历史古迹': ['古建筑', '博物馆', '文物', '历史遗迹', '文化遗产', '古迹'],
        '城市地标': ['现代建筑', '地标性建筑', '观景台', '城市象征', '摩天大楼'],
        '文化场所': ['艺术', '展览', '表演', '文化活动', '历史文化', '古迹'],
        '商业街区': ['购物', '美食', '娱乐', '时尚', '网红店', '特色小吃'],
        '主题乐园': ['游乐设施', '表演', '亲子', '刺激项目', '演出', '互动体验'],
        '乡村民宿': ['田园风光', '农家乐', '采摘', '乡村体验', '度假村']
      };

      const categoryTags = tagsByCategory[categories[categoryIndex]];
      const selectedTags = [];
      const tagCount = Math.floor(Math.random() * 3) + 1; // 1-3个标签

      for (let j = 0; j < tagCount; j++) {
        if (categoryTags && categoryTags.length > 0) {
          const randomTagIndex = Math.floor(Math.random() * categoryTags.length);
          selectedTags.push(categoryTags[randomTagIndex]);
          categoryTags.splice(randomTagIndex, 1); // 避免重复
        }
      }

      // 随机添加特性
      const allFeatures = ['trending', 'photoSpot', 'loved'];
      const features = [];
      const featureCount = Math.floor(Math.random() * 3); // 0-2个特性

      for (let j = 0; j < featureCount; j++) {
        const randomFeatureIndex = Math.floor(Math.random() * allFeatures.length);
        features.push(allFeatures[randomFeatureIndex]);
        allFeatures.splice(randomFeatureIndex, 1); // 避免重复
      }

      return {
        id: 100 + i + cities.indexOf(city) * 10,
        name: `${city.name}景点${i + 1}`,
        hotnessScore: baseScore,
        image: ['/images/forbidden-city.jpg', '/images/great-wall.jpg', '/images/west-lake.jpg'][i % 3],
        category: categories[categoryIndex],
        tags: selectedTags,
        features: features,
        isTrending: features.includes('trending')
      }
    }).sort((a, b) => b.hotnessScore - a.hotnessScore);
  }
}

// 处理城市选择变化
// 修改处理城市选择变化函数
const handleCityChange = async (cityCode) => {
  // 不立即显示加载状态，而是延迟200ms，避免短暂加载时的闪烁
  const loadingTimer = setTimeout(() => {
    loading.value = true;
  }, 200);

  // 预加载图片资源
  const preloadImages = (spots) => {
    spots.forEach(spot => {
      const img = new Image();
      img.src = spot.image || '/images/default-spot.jpg';
    });
  }

  try {
    // 获取景点数据
    const spots = mockHotspots[cityCode] || [];

    // 排序逻辑
    const sortedSpots = [...spots].sort((a, b) => {
      if (sortMethod.value === 'trending') {
        if (a.isTrending && !b.isTrending) return -1;
        if (!a.isTrending && b.isTrending) return 1;
      }
      return b.hotnessScore - a.hotnessScore;
    });

    // 预加载图片资源
    preloadImages(sortedSpots);

    // 使用缓存区来存储处理后的数据
    const processedSpots = sortedSpots;

    // 延迟设置数据，确保DOM更新在同一帧中完成
    await new Promise(resolve => setTimeout(resolve, 300));

    // 取消加载定时器，避免设置数据后立即显示加载状态
    clearTimeout(loadingTimer);

    // 先清空hotspots，再设置新数据，避免两组数据混合显示
    hotspots.value = [];

    // 通过nextTick确保DOM已经更新，然后设置新数据
    await nextTick();
    hotspots.value = processedSpots;

    // 最后才关闭加载状态，确保平滑过渡
    loading.value = false;
  } catch (error) {
    console.error('获取热门景点失败:', error);
    ElMessage.error('获取数据失败，请稍后重试');
    clearTimeout(loadingTimer);
    loading.value = false;
  }
}
// 排序景点数据
const sortSpots = () => {
  if (!hotspots.value.length) return;

  if (sortMethod.value === 'hot') {
    hotspots.value = [...hotspots.value].sort((a, b) => b.hotnessScore - a.hotnessScore);
  } else if (sortMethod.value === 'trending') {
    hotspots.value = [...hotspots.value].sort((a, b) => {
      if (a.isTrending && !b.isTrending) return -1;
      if (!a.isTrending && b.isTrending) return 1;
      return b.hotnessScore - a.hotnessScore;
    });
  }
}

// 获取景点标签
const getSpotTags = (spot) => {
  return spot.tags || [];
}

// 获取景点分类
const getSpotCategory = (spot) => {
  return spot.category || '';
}

// 判断是否有特定特性
const hasFeature = (spot, feature) => {
  return spot.features && spot.features.includes(feature);
}

// 获取标签类型
const getTagType = (index) => {
  const types = ['', 'success', 'warning', 'info', 'danger'];
  return types[index % types.length];
}

// 获取热度等级样式
const getHotnessBadgeClass = (score) => {
  if (score >= 90) return 'super-hot';
  if (score >= 80) return 'very-hot';
  if (score >= 70) return 'hot';
  return 'normal';
}

// 判断是否为焦点景点
const isSpotlight = (spot) => {
  return spot.hotnessScore >= 90;
}

// 获取景点图片
const getSpotImage = (spot) => {
  return spot.image || '/images/default-spot.jpg';
}

// 获取景点简短描述
const getSpotDescription = (spot) => {
  const category = getSpotCategory(spot);
  const tags = getSpotTags(spot);

  return `${spot.name}是${selectedCity.value === 'beijing' ? '北京' :
    selectedCity.value === 'shanghai' ? '上海' :
      selectedCity.value === 'hangzhou' ? '杭州' :
        selectedCity.value === 'wuhan' ? '武汉' : '当地'}著名的${category}，${tags.length > 0 ? '以' + tags.join('、') + '闻名' : '受到游客喜爱'}。`;
}

// 获取城市名称
const getCityName = () => {
  const city = cities.find(c => c.code === selectedCity.value);
  return city ? city.name : '';
}

// 获取城市描述
const getCityDescription = () => {
  return cityDescriptions[selectedCity.value] || '探索这座城市最热门的打卡地点';
}

// 获取城市横幅样式
const getCityBannerStyle = () => {
  const banner = cityBanners[selectedCity.value] || cityBanners.default;
  return {
    backgroundImage: `linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.7)), url(${banner})`
  };
}

const generateRandomVisitorCount = (spot) => {
  // 使用景点ID和名称作为种子
  const seed = `${spot.id}_${spot.name}_visitors`;
  const rng = seededRandom(seed);
  return rng.nextInt(100, 999) + 'K+';
}

// 生成随机评论数量
const generateRandomCommentCount = (spot) => {
  const seed = `${spot.id}_${spot.name}_comments`;
  const rng = seededRandom(seed);
  return rng.nextInt(1000, 9999);
}

// 生成随机照片数量
const generateRandomPhotoCount = (spot) => {
  const seed = `${spot.id}_${spot.name}_photos`;
  const rng = seededRandom(seed);
  return rng.nextInt(1000, 5999) + '+';
}

// 获取城市景点数量
const getSpotCount = (cityCode) => {
  return mockHotspots[cityCode] ? mockHotspots[cityCode].length : 0;
}

// 关闭对话框
const handleClose = () => {
  dialogVisible.value = false;
}

// 查看景点详情
const viewSpotDetail = (spot) => {
  // 检查是否有JSON数据
  if (spot.jsonData) {
    const jsonData = spot.jsonData;

    // 提取数据
    const description = `${jsonData.basic_info.spot_name}是武汉著名的网红打卡地。${extractTopicsDescription(jsonData.topics)
      }`;

    // 获取关键词
    const keywords = jsonData.keywords.combined.map(item => ({
      text: item.word,
      weight: Math.round(item.weight * 10)
    }));

    // 提取情感分析数据
    const sentimentData = {
      positive: jsonData.sentiment_analysis.stats.positive_percentage,
      neutral: jsonData.sentiment_analysis.stats.neutral_percentage,
      negative: jsonData.sentiment_analysis.stats.negative_percentage
    };

    // 构建用户关注点
    const userFocusPoints = jsonData.focus_points.map(point => ({
      name: point.category,
      value: Math.min(100, Math.round(point.score / 10))
    }));

    // 获取高评分旅行贴士
    const travelTips = extractTopTravelTips(jsonData.travel_tips);

    // 构建访问者趋势(模拟数据)
    const visitorTrends = generateVisitorTrends();

    // 设置详情数据
    selectedSpot.value = {
      ...spot,
      jsonData,
      description,
      address: `武汉市，详细位置请参考地图`,
      openingHours: getOpeningHours(jsonData),
      ticketPrice: getTicketInfo(jsonData),
      bestVisitTime: getBestVisitTime(jsonData),
      analytics: {
        sentimentData,
        keywords,
        userFocusPoints,
        visitorTrends,
        travelTips,
        topics: jsonData.topics,
        comments: {
          positive: jsonData.sentiment_analysis.positive_comments || [],
          negative: jsonData.sentiment_analysis.negative_comments || []
        }
      }
    }
  } else {
    // 使用默认模拟数据
    selectedSpot.value = {
      ...spot,
      // 添加模拟的详细数据
      description: getSpotDescription(spot),
      address: `${selectedCity.value === 'beijing' ? '北京市' : selectedCity.value === 'shanghai' ? '上海市' : selectedCity.value === 'hangzhou' ? '杭州市' : selectedCity.value}某区某路XXX号`,
      openingHours: '09:00-18:00',
      ticketPrice: '￥60-120',
      bestVisitTime: '4-10月',
      analytics: {
        sentimentData: {
          positive: Math.floor(Math.random() * 25) + 60, // 60-85%
          neutral: Math.floor(Math.random() * 15) + 10, // 10-25%
          negative: Math.floor(Math.random() * 10) + 5, // 5-15%
        },
        keywords: [
          { text: '风景优美', weight: 10 },
          { text: '拍照打卡', weight: 9 },
          { text: '人气旺', weight: 8 },
          { text: '文化底蕴', weight: 7 },
          { text: '适合遛娃', weight: 6 },
          { text: '网红景点', weight: 8 },
          { text: '交通便利', weight: 5 },
          { text: '历史悠久', weight: 6 }
        ],
        visitorTrends: [
          { month: '1月', count: Math.floor(Math.random() * 5000) + 1000 },
          { month: '2月', count: Math.floor(Math.random() * 5000) + 1000 },
          { month: '3月', count: Math.floor(Math.random() * 5000) + 3000 },
          { month: '4月', count: Math.floor(Math.random() * 10000) + 5000 },
          { month: '5月', count: Math.floor(Math.random() * 10000) + 8000 },
          { month: '6月', count: Math.floor(Math.random() * 10000) + 10000 },
          { month: '7月', count: Math.floor(Math.random() * 15000) + 15000 },
          { month: '8月', count: Math.floor(Math.random() * 15000) + 15000 },
          { month: '9月', count: Math.floor(Math.random() * 10000) + 10000 },
          { month: '10月', count: Math.floor(Math.random() * 10000) + 8000 },
          { month: '11月', count: Math.floor(Math.random() * 6000) + 3000 },
          { month: '12月', count: Math.floor(Math.random() * 5000) + 2000 }
        ],
        userFocusPoints: [
          { name: '景观', value: Math.floor(Math.random() * 30) + 70 },
          { name: '文化', value: Math.floor(Math.random() * 40) + 40 },
          { name: '拍照', value: Math.floor(Math.random() * 30) + 60 },
          { name: '美食', value: Math.floor(Math.random() * 40) + 30 },
          { name: '交通', value: Math.floor(Math.random() * 30) + 40 },
          { name: '服务', value: Math.floor(Math.random() * 30) + 50 }
        ],
        travelTips: [
          '提前网上预约门票可享受优惠',
          '旺季需提前1-2小时到达避免排队',
          '建议携带充电宝和足够的水',
          '景区内有专业摄影服务',
          '出口处有特色纪念品商店'
        ]
      }
    }
  }
  detailVisible.value = true;
}

// 辅助函数 - 从topics生成描述
function extractTopicsDescription(topics) {
  if (!topics || topics.length === 0) return '';

  return topics.slice(0, 2).map(topic =>
    `这里以${topic.name}闻名，特色包括${topic.keywords.slice(0, 3).map(k => k.word).join('、')}`
  ).join('。');
}

// 辅助函数 - 提取高评分旅行贴士
function extractTopTravelTips(tips) {
  if (!tips) return [];

  const allTips = [];
  Object.keys(tips).forEach(category => {
    if (Array.isArray(tips[category]) && tips[category].length > 0) {
      // 取每个分类中评分最高的提示
      allTips.push(tips[category][0].tip);
    }
  });

  return allTips.slice(0, 5);
}

// 辅助函数 - 生成游客趋势数据
function generateVisitorTrends() {
  return [
    { month: '1月', count: Math.floor(Math.random() * 5000) + 1000 },
    { month: '2月', count: Math.floor(Math.random() * 5000) + 1000 },
    { month: '3月', count: Math.floor(Math.random() * 5000) + 3000 },
    { month: '4月', count: Math.floor(Math.random() * 10000) + 5000 },
    { month: '5月', count: Math.floor(Math.random() * 10000) + 8000 },
    { month: '6月', count: Math.floor(Math.random() * 10000) + 10000 },
    { month: '7月', count: Math.floor(Math.random() * 15000) + 15000 },
    { month: '8月', count: Math.floor(Math.random() * 15000) + 15000 },
    { month: '9月', count: Math.floor(Math.random() * 10000) + 10000 },
    { month: '10月', count: Math.floor(Math.random() * 10000) + 8000 },
    { month: '11月', count: Math.floor(Math.random() * 6000) + 3000 },
    { month: '12月', count: Math.floor(Math.random() * 5000) + 2000 }
  ];
}

// 辅助函数 - 获取开放时间
function getOpeningHours(jsonData) {
  // 尝试从旅行贴士中提取开放时间信息
  const timeCategory = jsonData.travel_tips.timing || jsonData.travel_tips.时间;
  if (timeCategory && timeCategory.length > 0) {
    // 查找包含开放时间的提示
    for (const tip of timeCategory) {
      if (tip.tip.includes('开放时间') || tip.tip.includes('开放')) {
        return tip.tip.replace(/.*开放时间[:：]?\s*/g, '').split('，')[0];
      }
    }
  }
  return '09:00-17:00 (请以景区公告为准)';
}

// 辅助函数 - 获取门票信息
function getTicketInfo(jsonData) {
  // 尝试从旅行贴士中提取门票信息
  const costCategory = jsonData.travel_tips.cost || jsonData.travel_tips.费用;
  if (costCategory && costCategory.length > 0) {
    // 查找包含门票或票价的提示
    for (const tip of costCategory) {
      if (tip.tip.includes('门票') || tip.tip.includes('票价') || tip.tip.includes('免费')) {
        return tip.tip;
      }
    }
  }
  return '价格详询景区 (可能需要提前预约)';
}

// 辅助函数 - 获取最佳游览时间
function getBestVisitTime(jsonData) {
  // 从旅行贴士中寻找最佳游览时间信息
  const timeCategory = jsonData.travel_tips.timing || jsonData.travel_tips.时间;
  if (timeCategory && timeCategory.length > 0) {
    for (const tip of timeCategory) {
      if (tip.tip.includes('最佳') || tip.tip.includes('建议') || tip.tip.includes('早点')) {
        return tip.tip;
      }
    }
  }
  return '全年开放，旺季需提前预约';
}

function seededRandom(seed) {
  // 改进的字符串哈希函数，确保生成非负整数
  let hash = 0;
  for (let i = 0; i < seed.length; i++) {
    const char = seed.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;
    hash = hash >>> 0; // 使用无符号右移0位，强制转换为非负整数
  }
  
  // 创建一个简单的线性同余发生器
  const a = 1664525;
  const c = 1013904223;
  const m = Math.pow(2, 32);
  
  // 生成0到1之间的随机数
  let rand = () => {
    hash = ((a * hash + c) % m) >>> 0; // 确保结果是非负整数
    return hash / m;
  };
  
  return {
    // 返回min到max之间的整数
    nextInt: (min, max) => {
      return Math.floor(rand() * (max - min + 1) + min);
    }
  };
}
// 监听弹窗关闭，重置选择状态
watch(dialogVisible, (newVal) => {
  if (!newVal) {
    // 不重置城市选择，这样用户再次打开时可以保留之前的选择
    // selectedCity.value = '';
    // hotspots.value = [];
  }
})

// 初始引导展示
onMounted(() => {
  // 数据预加载，可以提前准备流行城市的数据
})
</script>

<style scoped>
.hotspot-dialog :deep(.el-dialog) {
  margin-top: 0vh !important;
  height: 85vh;
  /* 从90vh改为80vh，高度更适中 */
  display: flex;
  flex-direction: column;
  max-width: 1100px;
  /* 减小最大宽度 */
  border-radius: 12px;
  /* 添加圆角 */
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
  /* 增强阴影效果 */
}

.hotspot-dialog :deep(.el-dialog__body) {
  flex: 1;
  overflow: hidden;
  padding: 0;
  background-color: #f5f7fa;
  /* 设置背景色 */
  background-image: url('/images/travel-pattern-bg.jpg');
  /* 可以添加一个轻微的图案背景 */
  background-blend-mode: overlay;
}

.hotspot-container {
  height: 100%;
  display: flex;
  flex-direction: column;
  background-color: #f5f7fa;
  /* 更改背景色 */
  position: relative;
  border-radius: 0 0 12px 12px;
  /* 添加圆角 */
}

/* 控制面板 */
.control-panel {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 24px;
  background-color: #ffffff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
  z-index: 10;
}

.city-selector {
  flex: 1;
}

.city-select {
  width: 240px;
}

.city-option {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
}

.city-count {
  font-size: 12px;
  color: #909399;
}

.filter-tools {
  display: flex;
  align-items: center;
  gap: 24px;
}

.sort-label {
  margin-right: 8px;
  font-size: 14px;
  color: #606266;
}

.view-switcher {
  display: flex;
  gap: 8px;
}

/* 城市横幅 */
.city-banner {
  height: 180px;
  background-size: cover;
  background-position: center;
  position: relative;
  margin-bottom: 24px;
}

.city-info {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 24px;
  color: white;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}

.city-title {
  font-size: 32px;
  margin-bottom: 8px;
}

.city-description {
  font-size: 16px;
  max-width: 800px;
}

.content-area {
  flex: 1;
  overflow-y: auto;
  padding: 0 24px 24px;
  max-height: calc(80vh - 180px);
  /* 设置最大高度，减去顶部区域的高度 */
  scrollbar-width: thin;
  /* 细滚动条 */
}

.content-area::-webkit-scrollbar {
  width: 6px;
}

.content-area::-webkit-scrollbar-track {
  background-color: rgba(0, 0, 0, 0.05);
  border-radius: 3px;
}

.content-area::-webkit-scrollbar-thumb {
  background-color: rgba(0, 0, 0, 0.2);
  border-radius: 3px;
}

.content-area.no-city {
  display: flex;
  justify-content: center;
  align-items: center;
  background-image: url('/images/city-selection-bg.jpg');
  background-size: cover;
  background-position: center;
  padding: 0;
  /* 移除内边距，让背景完全填充 */
}

/* 空状态提示 */
.empty-state {
  text-align: center;
  padding: 30px 20px;
  max-width: 900px;
  background: rgba(255, 255, 255, 0.2);
  /* 改为半透明白色背景 */
  border-radius: 12px;
  color: white;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.15);
  backdrop-filter: blur(5px);
  /* 增强模糊效果 */
  width: 90%;
  margin: 0 auto;
}

.empty-icon {
  width: 100px;
  margin-bottom: 16px;
}

.empty-title {
  font-size: 22px;
  color: white;
  /* 从#303133改为白色 */
  margin-bottom: 8px;
  font-weight: 600;
  /* 加粗使其在深色背景上更清晰 */
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
  /* 添加文字阴影增强可读性 */
}

/* 描述文本改为浅灰白色 */
.empty-description {
  font-size: 14px;
  color: rgba(255, 255, 255, 0.9);
  /* 从#606266改为浅灰白色 */
  margin-bottom: 20px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
  /* 添加文字阴影增强可读性 */
}


.popular-cities {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  /* 固定为4列 */
  gap: 16px;
  margin: 20px auto;
  max-width: 900px;
  /* 限制最大宽度，使布局居中 */
}


.popular-city-card {
  height: 120px;
  /* 减小高度，一屏能显示更多 */
  border-radius: 12px;
  overflow: hidden;
  position: relative;
  cursor: pointer;
  transition: transform 0.3s ease, box-shadow 0.3s ease;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.popular-city-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.15);
}

.popular-city-image {
  width: 100%;
  height: 100%;
  background-size: cover;
  background-position: center;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

.popular-city-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.2));
  /* 增强渐变效果 */
}

.popular-city-name {
  color: white;
  font-weight: 600;
  font-size: 20px;
  padding: 0 16px;
  margin-bottom: 4px;
  position: relative;
  z-index: 2;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.6);
  /* 增强文字阴影 */
}

.popular-city-count {
  color: rgba(255, 255, 255, 0.9);
  /* 提高不透明度 */
  font-size: 14px;
  padding: 0 16px;
  margin-bottom: 16px;
  position: relative;
  z-index: 2;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
  /* 增强文字阴影 */
}

/* 网格视图 */
.spots-grid {
  padding-bottom: 20px;
}

.spots-grid-container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  /* 稍微减小最小宽度 */
  gap: 20px;
}

.spot-card {
  border-radius: 12px;
  overflow: hidden;
  background: white;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
  transition: all 0.3s ease;
  cursor: pointer;
}

.spot-card:hover {
  transform: translateY(-6px);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1);
}

.spot-card.spotlight {
  position: relative;
}

.spot-card.spotlight::before {
  content: '';
  position: absolute;
  top: -3px;
  left: -3px;
  right: -3px;
  bottom: -3px;
  background: linear-gradient(45deg, #ff9a9e 0%, #fad0c4 99%, #fad0c4 100%);
  z-index: -1;
  border-radius: 15px;
  animation: pulse 2s infinite;
}

@keyframes pulse {
  0% {
    opacity: 0.6;
  }

  50% {
    opacity: 1;
  }

  100% {
    opacity: 0.6;
  }
}

.spot-image {
  height: 180px;
  background-size: cover;
  background-position: center;
  position: relative;
}

.spot-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0));
}

.hotness-badge {
  position: absolute;
  top: 12px;
  right: 12px;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 20px;
  padding: 4px 10px;
  display: flex;
  align-items: center;
  gap: 4px;
  font-weight: 600;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.hotness-badge.super-hot {
  background: linear-gradient(135deg, #ff9a9e 0%, #fad0c4 99%, #fad0c4 100%);
  color: white;
}

.hotness-badge.very-hot {
  background: linear-gradient(135deg, #ffc3a0 0%, #ffafbd 100%);
  color: white;
}

.hotness-badge.hot {
  background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
  color: white;
}

.hotness-badge.normal {
  background: linear-gradient(135deg, #a1c4fd 0%, #c2e9fb 100%);
}

.hotness-icon {
  font-size: 14px;
}

.hotness-value {
  font-size: 14px;
}

.spot-category {
  position: absolute;
  top: 12px;
  left: 12px;
  background: rgba(0, 0, 0, 0.6);
  border-radius: 4px;
  padding: 3px 10px;
  color: white;
  font-size: 12px;
}

.spot-quick-info {
  position: absolute;
  bottom: 12px;
  left: 12px;
  display: flex;
  gap: 16px;
}

.like-count,
.comment-count {
  background: rgba(0, 0, 0, 0.6);
  border-radius: 16px;
  padding: 3px 10px;
  color: white;
  font-size: 12px;
  display: flex;
  align-items: center;
  gap: 4px;
}

.spot-info {
  padding: 16px;
}

.spot-name {
  margin: 0 0 8px;
  font-size: 18px;
  color: #303133;
}

.spot-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 12px;
}

.spot-features {
  display: flex;
  gap: 12px;
  margin-top: 12px;
}

.feature-item {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: #606266;
}

/* 列表视图 */
.spots-list {
  padding-bottom: 20px;
}

.spots-list-container {
  display: flex;
  flex-direction: column;
  gap: 16px;
  /* 减少项目间距 */
}

.spot-list-item {
  display: flex;
  background: white;
  border-radius: 12px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
  overflow: hidden;
  transition: all 0.3s ease;
  cursor: pointer;
}

.spot-list-item:hover {
  transform: translateY(-4px);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1);
}

.spot-list-item.spotlight {
  position: relative;
}

.spot-list-item.spotlight::before {
  content: '';
  position: absolute;
  top: -2px;
  left: -2px;
  right: -2px;
  bottom: -2px;
  background: linear-gradient(45deg, #ff9a9e 0%, #fad0c4 99%, #fad0c4 100%);
  z-index: -1;
  border-radius: 14px;
  animation: pulse 2s infinite;
}

.spot-list-image {
  width: 240px;
  height: 180px;
  flex-shrink: 0;
  background-size: cover;
  background-position: center;
  position: relative;
}

.spot-list-info {
  padding: 16px 20px;
  flex: 1;
}

.spot-list-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.spot-category-badge {
  background: #e6f7ff;
  color: #1890ff;
  padding: 2px 10px;
  border-radius: 4px;
  font-size: 12px;
}

.spot-description {
  margin: 12px 0;
  color: #606266;
  font-size: 14px;
  line-height: 1.6;
}

.spot-list-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 16px;
}

.spot-metrics {
  display: flex;
  gap: 20px;
}

.metric-item {
  display: flex;
  align-items: center;
  gap: 4px;
  color: #606266;
  font-size: 14px;
}

/* 加载状态 */
.loading-container {
  padding: 0;
  /* 移除内边距，与实际内容对齐 */
  animation: fadeIn 0.3s ease;
  width: 100%;
}

.loading-container.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 20px;
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

.skeleton-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 20px;
  width: 100%;
}

.skeleton-card {
  border-radius: 12px;
  overflow: hidden;
  background: white;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
}

/* 动画过渡 */
.spots-fade-enter-active,
.spots-fade-leave-active {
  transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}

.spots-fade-enter-from {
  opacity: 0;
  transform: translateY(20px);
}

.spots-fade-leave-to {
  opacity: 0;
}

/* 响应式调整 */
@media (max-width: 768px) {
  .filter-tools {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }

  .spots-grid-container {
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  }

  .spot-list-item {
    flex-direction: column;
  }

  .spot-list-image {
    width: 100%;
    height: 160px;
  }

  .city-banner {
    height: 140px;
    /* 减小高度 */
    background-size: cover;
    background-position: center;
    position: relative;
    margin-bottom: 16px;
    /* 减少底部间距 */
    border-radius: 8px;
    /* 添加圆角 */
    overflow: hidden;
    /* 确保圆角生效 */
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    /* 添加阴影 */
  }

  .skeleton-list-item {
    display: flex;
    background: white;
    border-radius: 12px;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
    overflow: hidden;
    margin-bottom: 16px;
  }

  .skeleton-image {
    position: relative;
  }

  .skeleton-badge,
  .skeleton-category {
    border-radius: 4px;
    overflow: hidden;
  }

  /* 增强过渡动画 */
  .spots-fade-enter-active {
    transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1);
    transition-delay: 0.1s;
    /* 延迟过渡开始，等待DOM就绪 */
  }

  .spots-fade-leave-active {
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    position: absolute;
    /* 确保离开元素不占位 */
    opacity: 0;
  }

  .spots-fade-enter-from {
    opacity: 0;
    transform: translateY(20px);
  }

  .spots-fade-leave-to {
    opacity: 0;
    transform: translateY(-20px);
  }
}
</style>